﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using StephenEssential;
using System.Xml.Linq;

namespace MinesweeperAuto
{
    class ChessBoard: Bitmap<ChessBoard.Grid>
    {
        public ChessBoard(int width, int height) : base(width, height, (x, y) => new Unknown()) { }

        public ChessBoard(int width, int height, int mineCount) : this(width, height)
        {
            if (width*height <= mineCount ||
                width <= 0 || height <= 0 || mineCount < 0) throw new Exception("The parameter has some error");
            Tools.RandomPermutation(width*height)
                .Pipe(randArr => Array.Resize(ref randArr, mineCount))
                .Pipe(arr => Array.ForEach(arr, num => this[num.ToPoint(width)] = new Mine()));
            ForEach((g, x, y) =>
            {
                if (g is Unknown) this[x, y] = new Flat(CalcMineCount(x, y));
            });
        }

        public int CalcMineCount(int x, int y)
        {
            return new Bitmap<Grid>(3, 3, (j, i) => this[x + j - 1, y + i - 1]).Count(g => g is Mine);
        }

        

        public List<Point> GetNeiborPoints(Point centerPoint, Func<Point, bool> predicate)
        {
            var x = centerPoint.X;
            var y = centerPoint.Y;
            return Tools.DecareProduct(
                    new[] {x - 1, x, x + 1},
                    new[] {y - 1, y, y + 1},
                    (j, i) => new Point(j, i),
                    (j, i) => new Point(j, i).Pipe(p => InRange(p) && p != centerPoint && predicate(p)))
                .ToList();
        }


        internal class Grid
        {
            public bool IsEmpty()
            {
                return this is Flat && ((Flat) this).SurroundingMineCount == 0;
            }
        }
        internal class Mine : Grid { }
        internal class Flat:Grid
        {
            public Flat(int surroundingMineCount)
            {
                SurroundingMineCount = surroundingMineCount;
            }

            public int SurroundingMineCount { get; private set; }
        }
        internal class Unknown : Grid { }

        public void ToHTML()
        {
            var document = new XDocument();
            
        }

        
    }
}
